package com.wskeee.ec.managers
{
	import flash.display.DisplayObject;
	import flash.display.Sprite;
	import flash.display.Stage;
	import flash.events.MouseEvent;
	import flash.events.TimerEvent;
	import flash.utils.Timer;
	
	import com.wskeee.ec.components.ToolTip;
	import com.wskeee.ec.core.EGlobal;
	import com.wskeee.ec.interfaces.IToolTip;
	import com.wskeee.ec.interfaces.IToolTipClient;
	import com.wskeee.ec.interfaces.IValidate;
	
	public class ToolTipManager implements IToolTipManager
	{
		public function ToolTipManager(stage:Stage)
		{
			this.stage = stage;
			toolTipClass = ToolTip;
		}
		//--------------------------------------------------------------------------
		//
		//  Properties
		//
		//--------------------------------------------------------------------------
		//---------------------
		//stage
		//---------------------
		private var stage:Stage;
		//---------------------
		//previousTarget
		//---------------------
		private var _previousTarget:DisplayObject;
		/**
		 * 记录上一个活动组件 
		 * @return 
		 * 
		 */
		public function get previousTarget():DisplayObject
		{
			return _previousTarget;
		}
		
		public function set previousTarget(value:DisplayObject):void
		{
			_previousTarget = value;
		}
		//---------------------
		//currentTarget
		//---------------------
		private var _currentTarget:DisplayObject;
		/**
		 * 当前活动的 组件 
		 * @return 
		 * 
		 */		
		public function get currentTarget():DisplayObject
		{
			return _currentTarget;
		}
		
		public function set currentTarget(value:DisplayObject):void
		{
			_currentTarget = value;
		}
		
		//---------------------
		//currentToolTip
		//---------------------
		private var _currentToolTip:IToolTip;
		/**
		 * 当前  Tip 实例 
		 * @return 
		 * 
		 */		
		public function get currentToolTip():IToolTip
		{
			return _currentToolTip;
		}
		
		public function set currentToolTip(value:IToolTip):void
		{
			_currentToolTip = value;
		}
		
		//---------------------
		//enabled
		//---------------------
		private var _enabled:Boolean = true;
		/**
		 * 禁用 or 启用提示  true/false
		 * @return 
		 * 
		 */		
		public function get enabled():Boolean
		{
			return _enabled;
		}
		
		public function set enabled(value:Boolean):void
		{
			_enabled = value;
		}
		
		//---------------------
		//hideDelay
		//---------------------
		private var _hideDelay:Number = 10000;
		/**
		 * 隐藏 延迟 
		 * @return 
		 * 
		 */		
		public function get hideDelay():Number
		{
			return _hideDelay;
		}
		
		public function set hideDelay(value:Number):void
		{
			_hideDelay = value;
		}
		
		//---------------------
		//scrubDelay
		//---------------------
		private var _scrubDelay:Number = 100;
		/**
		 * 设置createToolTip的最小间隔，防止用户从一个组件划到别一个组件时间过短
		 * @return 
		 * 
		 */		
		public function get scrubDelay():Number
		{
			return _scrubDelay;
		}
		
		public function set scrubDelay(value:Number):void
		{
			_scrubDelay = value;
		}
		
		//---------------------
		//showDelay
		//---------------------
		private var _showDelay:Number = 1000;
		/**
		 * 显示延迟，用户移到组件后，等showDelay时间后，提示才会弹出 ，
		 * 如果在showDelay内，用户移出组件，提示不会弹出
		 * @return 
		 * 
		 */		
		public function get showDelay():Number
		{
			return _showDelay;
		}
		
		public function set showDelay(value:Number):void
		{
			_showDelay = value;
		}
		
		//---------------------
		//toolTipClass
		//---------------------
		private var _toolTipClass:Class;
		/**
		 * 提示类，可自定提示的类，必须继承于 IToolTip  
		 * @return 
		 * 
		 */		
		public function get toolTipClass():Class
		{
			return _toolTipClass;
		}
		
		public function set toolTipClass(value:Class):void
		{
			_toolTipClass = value;
		}
		
		//--------------------------------------------------------------------------
		//
		//  method
		//
		//--------------------------------------------------------------------------
		//-----------------------------------------------------------------
		//  init
		//-----------------------------------------------------------------
		//-----------------------------------------------------------------
		//  varalbes
		//-----------------------------------------------------------------
		private var showDelayTimer:Timer;
		private var hideDelayTimer:Timer;
		private var scrubDelayTimer:Timer;
		private var hasInitialize:Boolean = false;
		
		private function initialize():void
		{
			hasInitialize = true;
			
			showDelayTimer = new Timer(0,1);
			hideDelayTimer = new Timer(0,1);
			scrubDelayTimer = new Timer(0,1);
			
			showDelayTimer.addEventListener(TimerEvent.TIMER_COMPLETE,onShowDelayTimerCompleteHandler);
			hideDelayTimer.addEventListener(TimerEvent.TIMER_COMPLETE,onHideDelayTimerCompleteHandler);
			scrubDelayTimer.addEventListener(TimerEvent.TIMER_COMPLETE,onScrubDelayTimerCompleteHandler);
		}
		
		protected function onScrubDelayTimerCompleteHandler(event:TimerEvent):void
		{
			destroyToolTip(currentToolTip);
		}
		
		private function onHideDelayTimerCompleteHandler(event:TimerEvent):void
		{
			removeToolTip();
		}
		
		private function onShowDelayTimerCompleteHandler(event:TimerEvent):void
		{
			popupToolTip();
		}
		//---------------------
		//registerToolTip
		//---------------------
		/**
		 * 组件注册提示 
		 * @param target		组件本身
		 * @param oldToolTip	旧提示
		 * @param newToolTip	新提示
		 * 
		 */		
		public function registerToolTip(target:DisplayObject, oldToolTip:String, newToolTip:String):void
		{
			
			if(!enabled)return;
			if(newToolTip)
			{
				target.addEventListener(MouseEvent.MOUSE_OVER,onTargetMouseOverHandler,false,0,true);
				target.addEventListener(MouseEvent.MOUSE_OUT,onTargetMouseOutHandler,false,0,true);
			}else if(oldToolTip && !newToolTip)
			{
				target.removeEventListener(MouseEvent.MOUSE_OVER,onTargetMouseOverHandler,false);
				target.removeEventListener(MouseEvent.MOUSE_OUT,onTargetMouseOutHandler,false);
			}
		}
		
		private function onTargetMouseOutHandler(event:MouseEvent):void
		{
			checkIfTargetChange(null);
		}
		
		private function onTargetMouseOverHandler(event:MouseEvent):void
		{
			checkIfTargetChange(event.currentTarget as DisplayObject);
		}
		
		//---------------------
		//registerErrorString
		//---------------------
		/**
		 * 注册错误提示，暂时保留 
		 * @param target
		 * @param oldErrorString
		 * @param newErrorString
		 * 
		 */		
		public function registerErrorString(target:DisplayObject, oldErrorString:String, newErrorString:String):void
		{
		}
		
		//---------------------
		//createToolTip
		//---------------------
		/**
		 * 创建一个提示 
		 * @param text					提示信息
		 * @param x						指定 x 位置
		 * @param y						揹定 y 集团
		 * @return 						
		 * 
		 */		
		public function createToolTip(text:String):IToolTip
		{
			return null;
		}
		
		//---------------------
		//destroyToolTip 
		//---------------------
		/**
		 * 销毁 toolTip 实例 
		 * @param toolTip
		 * 
		 */		
		public function destroyToolTip(toolTip:IToolTip):void
		{
			stage.removeChild(toolTip as DisplayObject);
			currentToolTip = null;
		}
		
		//--------------------------------------------------------------------------
		//
		//  utils
		//
		//--------------------------------------------------------------------------
		//---------------------
		//findTarget
		//---------------------
		private function findTarget(value:DisplayObject):DisplayObject
		{
			var ct:DisplayObject = value;
			while(ct)
			{
				if(ct is IToolTipClient)
					return ct as DisplayObject;
				ct = ct.parent;
			}
			return null;
		}
		
		//---------------------
		//checkIfTargetChange
		//---------------------
		/**
		 * 检查是否需要弹出提示 
		 * @param value
		 * 
		 */
		private function checkIfTargetChange(value:DisplayObject):void
		{
			if(!enabled)return;
			currentTarget = findTarget(value);
			if(currentTarget!=previousTarget)
			{
				targetChanage();
				previousTarget = currentTarget;
			}
		}
		
		//---------------------
		//targetChange
		//---------------------
		private function targetChanage():void
		{
			if(!hasInitialize)
				initialize();
			if(showDelayTimer.running)
				showDelayTimer.stop();
			if(hideDelayTimer.running)
				hideDelayTimer.stop();
			if(scrubDelayTimer.running)
				scrubDelayTimer.stop();
			
			if(currentToolTip)
			{
				if(currentTarget)
				{
					currentToolTip.text = IToolTipClient(currentTarget).toolTip;
					fixPosition();
				}else
				{
					removeToolTip();
				}
			}else
			{
				if(currentTarget)
				{
					if(showDelay!=0)
					{
						showDelayTimer.delay = showDelay;
						showDelayTimer.start();
					}else
					{
						popupToolTip();
					}
				}
			}
		}
		
		//---------------------
		//fixPosition
		//---------------------
		private function fixPosition():void
		{
			var sw:Number = stage.stageWidth;
			var sh:Number = stage.stageHeight;
			if(currentToolTip)
			{
				IValidate(currentToolTip).validateProperties();
				IValidate(currentToolTip).validateSize();
				IValidate(currentToolTip).validateDisplayList();
			}
			var x:Number = stage.mouseX;
			var y:Number = stage.mouseY;
			
			if(x+DisplayObject(currentToolTip).width>sw)
				x = sw - DisplayObject(currentToolTip).width;
			y += (y>sh/2) ? (-5 - DisplayObject(currentToolTip).height) : 22;
			DisplayObject(currentToolTip).x = x;
			DisplayObject(currentToolTip).y = y;
		}
		
		//---------------------
		//popuTips
		//---------------------
		private function popupToolTip():void
		{
			currentToolTip = new toolTipClass();
			Sprite(currentToolTip).mouseChildren = Sprite(currentToolTip).mouseEnabled = false;
			currentToolTip.text = IToolTipClient(currentTarget).toolTip;
			stage.addChild(currentToolTip as DisplayObject);
			fixPosition();
			if(hideDelayTimer.running)
				hideDelayTimer.stop();
			hideDelayTimer.delay = hideDelay;
			hideDelayTimer.start();
		}
		
		//---------------------
		//removeTips
		//---------------------
		private function removeToolTip():void
		{
			currentTarget = null;
			if(hideDelayTimer.running)
				hideDelayTimer.stop();
			if(scrubDelayTimer.running)
				scrubDelayTimer.stop();
			scrubDelayTimer.delay = scrubDelay;
			scrubDelayTimer.start();
		}
	}
}